﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

//全部子图形
namespace RoadSign.entity
{
    class GraphicList
    {
        public List<GraphicItem> items = new List<GraphicItem>();
        public List<ColorPoint> fillPoints = new List<ColorPoint>();  //填充操作时鼠标点击的点
        public Rectangle rectangle = new Rectangle();   //包围所画图形的最小矩形
        public Panel panel;
        public Graphics g;
        public Boolean minBig = false;

        public GraphicList(Panel panel, Graphics g)
        {
            this.panel = panel;
            this.g = g;
        }

        //以下为图形填充所需的API

        [DllImport("gdi32.dll")]

        public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

        [DllImport("gdi32.dll")]

        public static extern IntPtr CreateSolidBrush(int crColor);

        [DllImport("gdi32.dll")]

        public static extern bool ExtFloodFill(IntPtr hdc, int nXStart, int nYStart,

            int crColor, uint fuFillType);

        [DllImport("gdi32.dll")]

        public static extern bool DeleteObject(IntPtr hObject);

        [DllImport("gdi32.dll")]

        public static extern int GetPixel(IntPtr hdc, int x, int y);

        public static uint FLOODFILLBORDER = 0;

        public static uint FLOODFILLSURFACE = 1;


        //画全部图形
        public void paint()
        {
            panel.Refresh();//清空之前的绘图
            foreach (GraphicItem item in items)
            {
                item.paint(g);
            }
            paintFill();
        }

        //得到最后一个（当前画的） 
        public GraphicItem getLast()
        {
            if (items.Count > 0)
            {
                return items[items.Count - 1];
            }
            return null;
        }

        //回退
        public bool removeLast()
        {
            if (fillPoints.Count > 0)
            {
                return false;
            }
            getLast().removeLast();
            return true;
        }

        //填充
        public void fill(Color color)
        {
            Point point = panel.PointToClient(Control.MousePosition);//当前鼠标的位置
            fillPoints.Add(new ColorPoint(point.X, point.Y, color));
        }

        //绘制填充
        public void paintFill()
        {
            foreach (ColorPoint p in fillPoints)
            {
                IntPtr vDC = g.GetHdc();
                IntPtr vBrush = CreateSolidBrush(ColorTranslator.ToWin32(p.color));
                IntPtr vPreviouseBrush = SelectObject(vDC, vBrush);

                ExtFloodFill(vDC, p.X, p.Y, GetPixel(vDC, p.X, p.Y), FLOODFILLSURFACE);

                SelectObject(vDC, vPreviouseBrush);
                DeleteObject(vBrush);
                g.ReleaseHdc(vDC);
            }
        }

        //清空
        public void clear()
        {
            items = new List<GraphicItem>();
            fillPoints = new List<ColorPoint>();  //填充操作时鼠标点击的点
            rectangle = new Rectangle();
        }

        //移动
        public void move(Point startPoint, Point endPoint)
        {
            int moveX = endPoint.X - startPoint.X;
            int moveY = endPoint.Y - startPoint.Y;

            //移动图形
            for (int i = 0; i < items.Count; i++)
            {
                for (int j = 0; j < items[i].points.Count; j++)
                {
                    Point p = items[i].points[j];
                    items[i].points[j] = new Point(p.X + moveX, p.Y + moveY);
                }
            }

            //移动填充点击的点
            for (int i = 0; i < fillPoints.Count; i++)
            {
                ColorPoint p = fillPoints[i];
                fillPoints[i] = new ColorPoint(p.X + moveX, p.Y + moveY, p.color);
            }

            this.paint();
        }

        //得到边界
        public Dictionary<string, int> getBorder()
        {
            Dictionary<string, int> border = new Dictionary<string, int>();
            if (items.Count > 0 && items[0].points.Count > 0)//至少一个点
            {
                Point firstPoint = items[0].points[0];

                int right = firstPoint.X;
                int bottom = firstPoint.Y;
                int left = firstPoint.X;
                int top = firstPoint.Y;
                foreach (GraphicItem item in items)
                {
                    foreach (Point p in item.points)
                    {
                        if (p.X > right)
                            right = p.X;
                        if (p.X < left)
                            left = p.X;
                        if (p.Y > bottom)
                            bottom = p.Y;
                        if (p.Y < top)
                            top = p.Y;
                    }
                }
                border.Add("right", right);
                border.Add("bottom", bottom);
                border.Add("left", left);
                border.Add("top", top);
            }
            return border;
        }

        //求图形中点
        private Point getLoad()
        {
            Dictionary<string, int> border = getBorder();
            int right = border["right"];
            int left = border["left"];
            int bottom = border["bottom"];
            int top = border["top"];

            int x = right - left;
            int y = bottom - top;
            if (x <= 100 || y <= 100)//限制最小的大小
                minBig = true;
            else minBig = false;
            return new Point((bottom - top) / 2 + top, (right - left) / 2 + left);
        }

        //改变大小
        public void changeSize(int delta)
        {
            double multiple;//缩放倍数
            if (delta > 0)
            {
                multiple = 1.2;
            }
            else
            {
                multiple = 0.8;
            }
            Point mid = getLoad();
            if (!minBig || delta > 0)
            {
                //遍历，根据倍数改变每一点的坐标
                for (int i = 0; i < items.Count; i++)
                {
                    for (int j = 0; j < items[i].points.Count; j++)
                    {
                        Point p = items[i].points[j];
                        p.X = (int)((p.X - mid.X) * multiple + mid.X);
                        p.Y = (int)((p.Y - mid.Y) * multiple + mid.Y);
                        items[i].points[j] = p;
                    }
                }

                //遍历，根据倍数改变填充点击的点的坐标
                for (int i = 0; i < fillPoints.Count; i++)
                {
                    ColorPoint p = fillPoints[i];
                    p.X = (int)((p.X - mid.X) * multiple + mid.X);
                    p.Y = (int)((p.Y - mid.Y) * multiple + mid.Y);
                    fillPoints[i] = p;
                }

                this.paint();
            }

        }

        //改变大小(精确)
        public void changeSize(double multiple)
        {
            Point mid = getLoad();
            if (true)
            {
                //遍历，根据倍数改变每一点的坐标
                for (int i = 0; i < items.Count; i++)
                {
                    for (int j = 0; j < items[i].points.Count; j++)
                    {
                        Point p = items[i].points[j];
                        p.X = (int)((p.X - mid.X) * multiple + mid.X);
                        p.Y = (int)((p.Y - mid.Y) * multiple + mid.Y);
                        items[i].points[j] = p;
                    }
                }

                //遍历，根据倍数改变填充点击的点的坐标
                for (int i = 0; i < fillPoints.Count; i++)
                {
                    ColorPoint p = fillPoints[i];
                    p.X = (int)((p.X - mid.X) * multiple + mid.X);
                    p.Y = (int)((p.Y - mid.Y) * multiple + mid.Y);
                    fillPoints[i] = p;
                }

                this.paint();
            }

        }
    }
}
